// test_framework.c - Improved version with dynamic registration
#include "test_framework.h"
#include "../hisi_l0_mem_pool.h"
#include "test_common.h"

static struct proc_dir_entry *test_proc_entry;
static struct test_case *all_test_cases;
static int total_tests;
static LIST_HEAD(test_modules_list); // List of registered test modules

int test_debug_level = 2;
// External test cases - removed direct references, now using dynamic registration

static int test_proc_show(struct seq_file *m, void *v)
{
    int i;
    int passed = 0, failed = 0, total = 0;
    
    if (!all_test_cases) {
        seq_printf(m, "No test suite registered\n");
        return 0;
    }
    
    seq_printf(m, "====================\n");
    seq_printf(m, "Test Suite: L0 Memory Pool Tests\n");
    seq_printf(m, "====================\n\n");
    
    for (i = 0; i < total_tests; i++) {
        int result;
        
        seq_printf(m, "Test %d: %s\n", i+1, all_test_cases[i].name);
        result = all_test_cases[i].test_func(m);
        
        if (result == 0) {
            passed++;
        } else {
            failed++;
        }
        total++;
        
        seq_printf(m, "\n");
    }
    
    seq_printf(m, "====================\n");
    seq_printf(m, "Test Results Summary:\n");
    seq_printf(m, "Total: %d, Passed: %d, Failed: %d\n", total, passed, failed);
    seq_printf(m, "====================\n");
    
    return 0;
}

static int test_proc_open(struct inode *inode, struct file *file)
{
    return single_open(file, test_proc_show, NULL);
}

static const struct proc_ops test_proc_ops = {
    .proc_open = test_proc_open,
    .proc_read = seq_read,
    .proc_lseek = seq_lseek,
    .proc_release = single_release,
};

int register_test_module(test_module_t *module)
{
    if (!module || !module->test_cases || module->num_tests <= 0) {
        return -EINVAL;
    }
    
    list_add_tail(&module->list, &test_modules_list);
    pr_info("Registered test module: %s with %d tests\n", 
            module->module_name, module->num_tests);
    return 0;
}

void unregister_test_module(test_module_t *module)
{
    if (module) {
        list_del(&module->list);
        pr_info("Unregistered test module: %s\n", module->module_name);
    }
}

int register_test_suite(const char *name)
{
    struct test_module *module;
    int total = 0;
    int offset = 0;
    int i;
    
    // Calculate total number of tests
    list_for_each_entry(module, &test_modules_list, list) {
        total += module->num_tests;
    }
    
    // Allocate memory for all test cases
    all_test_cases = kzalloc(total * sizeof(struct test_case), GFP_KERNEL);
    if (!all_test_cases) {
        return -ENOMEM;
    }
    
    // Copy all test cases from registered modules
    list_for_each_entry(module, &test_modules_list, list) {
        for (i = 0; i < module->num_tests; i++) {
            all_test_cases[offset++] = module->test_cases[i];
        }
    }
    
    total_tests = total;
    
    test_proc_entry = proc_create("l0_mem_pool_test", 0444, NULL, &test_proc_ops);
    if (!test_proc_entry) {
        pr_err("Failed to create proc entry for test suite\n");
        kfree(all_test_cases);
        all_test_cases = NULL;
        return -ENOMEM;
    }
    
    pr_info("Test suite '%s' registered with %d tests\n", name, total_tests);
    return 0;
}

void unregister_test_suite(void)
{
    if (test_proc_entry) {
        proc_remove(test_proc_entry);
        test_proc_entry = NULL;
    }
    
    if (all_test_cases) {
        kfree(all_test_cases);
        all_test_cases = NULL;
    }
    
    pr_info("Test suite unregistered\n");
}